/**
 * Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.opsli.modulars.business.valveDeviceNowHis.web;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.convert.Convert;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.opsli.api.web.business.valveDeviceNowHis.ValveDeviceNowHisRestApi;
import org.opsli.api.wrapper.business.valveDeviceNowHis.ValveDeviceNowHisModel;
import org.opsli.api.wrapper.business.valveStation.ValveStationModel;
import org.opsli.common.annotation.RequiresPermissionsCus;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.opsli.api.base.result.ResultVo;
import org.opsli.common.annotation.ApiRestController;
import org.opsli.common.annotation.EnableLog;
import org.opsli.core.base.controller.BaseRestController;
import org.opsli.core.persistence.Page;
import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
import org.opsli.core.utils.UserUtil;
import org.opsli.modulars.business.valveDevice.service.IValveDeviceService;
import org.opsli.modulars.business.valveStation.service.IValveStationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

import org.opsli.modulars.business.valveDeviceNowHis.entity.ValveDeviceNowHis;
import org.opsli.modulars.business.valveDeviceNowHis.service.IValveDeviceNowHisService;

/**
 * 实时数据历史 Controller
 *
 * @author zk
 * @date 2021-11-01 15:06:09
 */
@Api(tags = ValveDeviceNowHisRestApi.TITLE)
@Slf4j
@ApiRestController("/valveDeviceNowHis")
public class ValveDeviceNowHisRestController extends BaseRestController<ValveDeviceNowHis, ValveDeviceNowHisModel, IValveDeviceNowHisService>
    implements ValveDeviceNowHisRestApi {

    @Autowired
    private IValveStationService patrolStationService;
    @Autowired
    private IValveDeviceService deviceService;
    @Autowired
    private IValveStationService iValveStationService;


    /**
    * 实时数据历史 查一条
    * @param model 模型
    * @return ResultVo
    */
    @ApiOperation(value = "获得单条实时数据历史", notes = "获得单条实时数据历史 - ID")
    @RequiresPermissions("valvedevicenowhis_select")
    @Override
    public ResultVo<ValveDeviceNowHisModel> get(ValveDeviceNowHisModel model) {
        // 如果系统内部调用 则直接查数据库
        if(model != null && model.getIzApi() != null && model.getIzApi()){
            model = IService.get(model);
        }
        return ResultVo.success(model);
    }

    /**
    * 实时数据历史 查询分页
    * @param pageNo 当前页
    * @param pageSize 每页条数
    * @param request request
    * @return ResultVo
    */
    @ApiOperation(value = "获得分页数据", notes = "获得分页数据 - 查询构造器")
    @Override
    public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) {

        Map<String,String[]> queryMap = new LinkedHashMap(request.getParameterMap());
        String devid=UserUtil.getSysUser().getCompanyId();
        if(!devid.equals("123")){
            queryMap.put("devid_EQ",new String[]{devid});
        }
        String[] o=queryMap.get("valveName_LIKE");
        if(o!=null){
            String valveName=o[0];
            ValveStationModel valveStationModel=patrolStationService.getOneValve(valveName);
            if(valveStationModel!=null){
                queryMap.put("valveId_EQ",new String[]{valveStationModel.getId()});
            }
            /*System.out.println(valveName);*/
        }
        QueryBuilder<ValveDeviceNowHis> queryBuilder = new WebQueryBuilder<>(entityClazz, queryMap);
        Page<ValveDeviceNowHis, ValveDeviceNowHisModel> page = new Page<>(pageNo, pageSize);
        page.setQueryWrapper(queryBuilder.build());
        page = IService.findPage(page);
        if(page.getPageData().getRows()!=null&&page.getPageData().getRows().size()>0){
            List<ValveDeviceNowHisModel> list=(List<ValveDeviceNowHisModel>)page.getPageData().getRows();
            for(ValveDeviceNowHisModel model:list){
                ValveStationModel stationModel=patrolStationService.get(model.getValveId());
                model.setValveName(stationModel.getStationName());
            }
            page.getPageData().setRows(list);
        }

        return ResultVo.success(page.getPageData());
    }

    /**
    * 实时数据历史 新增
    * @param model 模型
    * @return ResultVo
    */
    @ApiOperation(value = "新增实时数据历史数据", notes = "新增实时数据历史数据")
    @RequiresPermissions("valvedevicenowhis_insert")
    @EnableLog
    @Override
    public ResultVo<?> insert(ValveDeviceNowHisModel model) {
        // 调用新增方法
        IService.insert(model);
        return ResultVo.success("新增实时数据历史成功");
    }

    /**
    * 实时数据历史 修改
    * @param model 模型
    * @return ResultVo
    */
    @ApiOperation(value = "修改实时数据历史数据", notes = "修改实时数据历史数据")
    @RequiresPermissions("valvedevicenowhis_update")
    @EnableLog
    @Override
    public ResultVo<?> update(ValveDeviceNowHisModel model) {
        // 调用修改方法
        IService.update(model);
        return ResultVo.success("修改实时数据历史成功");
    }


    /**
    * 实时数据历史 删除
    * @param id ID
    * @return ResultVo
    */
    @ApiOperation(value = "删除实时数据历史数据", notes = "删除实时数据历史数据")
    @RequiresPermissions("valvedevicenowhis_update")
    @EnableLog
    @Override
    public ResultVo<?> del(String id){
        IService.delete(id);
        return ResultVo.success("删除实时数据历史成功");
    }

    /**
    * 实时数据历史 批量删除
    * @param ids ID 数组
    * @return ResultVo
    */
    @ApiOperation(value = "批量删除实时数据历史数据", notes = "批量删除实时数据历史数据")
    @RequiresPermissions("valvedevicenowhis_update")
    @EnableLog
    @Override
    public ResultVo<?> delAll(String ids){
        String[] idArray = Convert.toStrArray(ids);
        IService.deleteAll(idArray);
        return ResultVo.success("批量删除实时数据历史成功");
    }


    /**
    * 实时数据历史 Excel 导出
    * 注：这里 RequiresPermissionsCus 引入的是 自定义鉴权注解
    *
    * 导出时，Token认证和方法权限认证 全部都由自定义完成
    * 因为在 导出不成功时，需要推送错误信息，
    * 前端直接走下载流，当失败时无法获得失败信息，即使前后端换一种方式后端推送二进制文件前端再次解析也是最少2倍的耗时
    * ，且如果数据量过大，前端进行渲染时直接会把浏览器卡死
    * 而直接开启socket接口推送显然是太过浪费资源了，所以目前采用Java最原始的手段
    * response 推送 javascript代码 alert 提示报错信息
    *
    * @param request request
    * @param response response
    */
    @ApiOperation(value = "导出Excel", notes = "导出Excel")
    @EnableLog
    @Override
    public void exportExcel(HttpServletRequest request, HttpServletResponse response) {

        Map<String,String[]> queryMap = new LinkedHashMap(request.getParameterMap());
        String devid=UserUtil.getSysUser().getCompanyId();
        ValveDeviceNowHis valveDeviceNowHis=new ValveDeviceNowHis();
        String[] o=queryMap.get("deviceId_LIKE");
        String deviceId = null;
        if(o!=null) {
             deviceId = o[0];
        }
        valveDeviceNowHis.setDeviceId(deviceId);
        valveDeviceNowHis.setDevid(devid);
        List<ValveDeviceNowHisModel> vdnList = IService.getExcelList(valveDeviceNowHis);
        //HSSFWorkbook一个sheet最大行数 65536 超出截取
        if(vdnList.size() >= 65535){
            vdnList = vdnList.subList(0, 65535);
        }
        List<ValveStationModel> stationList = iValveStationService.findList(devid);

        for (ValveDeviceNowHisModel hisModel:vdnList){
            for (ValveStationModel stationModel:stationList){
                if(null != hisModel.getValveId() && null != stationModel.getId()){
                    if(hisModel.getValveId().equals(stationModel.getId())){
                        hisModel.setValveName(stationModel.getStationName());
                    }
                }
            }
        }
        //excel标题
        String[] title = {"序号","阀门井名称","阀门井编号","设备编号","更新时间","电池电压(V)","浓度(%)","湿度(%)","温度(°C)","水位状态","门开状态","移动状态"};
        SimpleDateFormat formatter  = new SimpleDateFormat("yyyy-MM-dd");
        String  dString = formatter.format(new Date());

        //excel文件名
        String fileName = "阀门井历史数据"+dString+".xlsx";

        //sheet名
        String sheetName = "阀门井历史数据表";

        // 内容
        List<List<String>> contentList = new ArrayList<>();

        // 数据需要对应标题字段位置
        for (int i = 0; i < vdnList.size(); i++) {
            ValveDeviceNowHisModel obj = vdnList.get(i);
            List<String> shell = new LinkedList();
            shell.add(i + 1 + "");
            shell.add(obj.getValveName());
            shell.add(obj.getValveId());
            shell.add(obj.getDeviceId());
            shell.add(obj.getLastTime());
            shell.add(obj.getVoltage());
            shell.add(obj.getPotency());
            shell.add(obj.getHum());
            shell.add(obj.getTemp());
            shell.add((obj.getBit2().equals("0"))?"正常":"报警");
            shell.add((obj.getBit3().equals("0"))?"正常":"报警");
            shell.add((obj.getBit6().equals("0"))?"正常":"报警");

            contentList.add(shell);
        }

        //创建HSSFWorkbook
        HSSFWorkbook wb = ExcelUtil.getHSSFWorkbook(sheetName, title, contentList, null);

        //响应到客户端
        try {
            this.setResponseHeader(response, fileName);
            OutputStream os = response.getOutputStream();
            wb.write(os);
            os.flush();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //发送响应流方法
    public void setResponseHeader(HttpServletResponse response, String fileName) {
        try {
            try {
                fileName = new String(fileName.getBytes(),"ISO8859-1");
            } catch (UnsupportedEncodingException e) {
                System.out.println("导出报表发送响应流异常 : " + e.getMessage());
                e.printStackTrace();
            }
            response.setContentType("application/octet-stream;charset=ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename="+ fileName);
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
        } catch (Exception ex) {
            System.out.println("导出报表发送响应流异常 : " + ex.getMessage());
            ex.printStackTrace();
        }
    }


    /**
    * 实时数据历史 Excel 导入
    * 注：这里 RequiresPermissions 引入的是 Shiro原生鉴权注解
    * @param request 文件流 request
    * @return ResultVo
    */
    @ApiOperation(value = "导入Excel", notes = "导入Excel")
    @RequiresPermissions("valvedevicenowhis_import")
    @EnableLog
    @Override
    public ResultVo<?> importExcel(MultipartHttpServletRequest request) {
        return super.importExcel(request);
    }

    /**
    * 实时数据历史 Excel 下载导入模版
    * 注：这里 RequiresPermissionsCus 引入的是 自定义鉴权注解
    * @param response response
    */
    @ApiOperation(value = "导出Excel模版", notes = "导出Excel模版")
    @RequiresPermissionsCus("valvedevicenowhis_import")
    @Override
    public void importTemplate(HttpServletResponse response) {
        // 当前方法
        Method method = ReflectUtil.getMethodByName(this.getClass(), "importTemplate");
        super.importTemplate(ValveDeviceNowHisRestApi.SUB_TITLE, response, method);
    }

}
